package com.linkgie.galaxyframework.utils;

import java.math.BigInteger;

public class BigInt {

	public static final BigInteger ZERO;

	public static final BigInteger ONE;

	private static final BigInteger[] BIGINT_CACHE;

	private static final int DEFAULT_CACHE_LOW = -128;

	private static final int DEFAULT_CACHE_HIGHT = 127;
	
	private static final int CACHE_LOW;
	
	private static final int CACHE_HIGHT;

	static {
		CACHE_LOW =  DEFAULT_CACHE_LOW;
		CACHE_HIGHT = DEFAULT_CACHE_HIGHT;
		BIGINT_CACHE =new BigInteger[CACHE_HIGHT-CACHE_LOW + 1];
		int v = CACHE_LOW;
		for (int i = 0; i < BIGINT_CACHE.length; i++) {
			BIGINT_CACHE[i] = new BigInteger(BinaryUtils.toBytes(v++));
		}
		
		ZERO = valueOf(0);
		ONE = valueOf(1);
	}
	
	public static BigInteger valueOf(int value) {
		if (value >= CACHE_LOW && value <= CACHE_HIGHT) {
			return BIGINT_CACHE[value + (-CACHE_LOW)];
		}
		return new BigInteger(BinaryUtils.toBytes(value));
	}
	
	public static BigInteger valueOf(long value) {
		if (value >= CACHE_LOW && value <= CACHE_HIGHT) {
			return BIGINT_CACHE[(int)value + (-CACHE_LOW)];
		}
		return new BigInteger(BinaryUtils.toBytes(value));
	}

	/**
	 * 执行大整数加 1 操作，返回结果；
	 * 
	 * @param value
	 * @return
	 */
	public static byte[] increment(byte[] value) {
		return add(value, 1);
	}

	/**
	 * 执行大整数减 1 操作，返回结果；
	 * 
	 * @param value
	 * @return
	 */
	public static byte[] decrement(byte[] value) {
		return subtract(value, 1);
	}

	public static byte[] add(byte[] value1, int value2) {
		BigInteger v1 = new BigInteger(value1);
		BigInteger v2 = valueOf(value2);
		return v1.add(v2).toByteArray();
	}

	public static byte[] add(byte[] value1, long value2) {
		BigInteger v1 = new BigInteger(value1);
		BigInteger v2 = valueOf(value2);
		return v1.add(v2).toByteArray();
	}
	
	public static byte[] subtract(byte[] value1, int value2) {
		BigInteger v1 = new BigInteger(value1);
		BigInteger v2 = valueOf(value2);
		return v1.subtract(v2).toByteArray();
	}
	
	public static byte[] subtract(byte[] value1, long value2) {
		BigInteger v1 = new BigInteger(value1);
		BigInteger v2 = valueOf(value2);
		return v1.subtract(v2).toByteArray();
	}

}
